package com.xieman.anti.replay.utils;

import com.xieman.anti.replay.annotation.Priority;
import com.xieman.anti.replay.exception.ClassLoaderException;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

public class ClassLoader {

    public static <T> T load(Class<T> clazz) {
        return ClassLoader.load(clazz, ClassLoader.class.getClassLoader());
    }

    public static <T> List<T> loadAll(Class<T> clazz, java.lang.ClassLoader classLoader) {
        List<T> list = new ArrayList<>();
        executeLoad(clazz, classLoader).forEach(loader -> list.add(loader));
        return list;
    }

    public static <T> T load(Class<T> clazz, java.lang.ClassLoader classLoader) {
        T service = null;
        int highestPriority = Priority.DEFAULT_PRIORITY;

        for (T loader : executeLoad(clazz, classLoader)) {
            final Priority priority = loader.getClass().getAnnotation(Priority.class);
            if (service == null || priority.value() < highestPriority) {
                service = loader;
                highestPriority = priority.value();
            }
        }

        return service;
    }

    public static <T> ServiceLoader<T> executeLoad(
            Class<T> clazz, java.lang.ClassLoader classLoader) {
        final ServiceLoader<T> loaders = ServiceLoader.load(clazz, classLoader);

        if (loaders == null) {
            throw new ClassLoaderException();
        }

        return loaders;
    }
}
